﻿using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Linq;
using System.Text.RegularExpressions;
using MediaAssistant.Data;
using MediaAssistant.Helper;
using MediaAssistant.Management;
using MefBasic;
using MefBasic.Commans;
using MefBasic.Threading;
using MediaAssistant.DAL;
using MediaAssistant.DAL.Constants;

namespace MediaAssistant.Controls.MovieSearchControl
{
    [Export]
    public class MovieSearchControlPresenter:APresenter<MovieSearchControlView>
    {
        [ImportingConstructor]
        public MovieSearchControlPresenter(MovieSearchControlView view)
            : base(view)
        {
            SearchCommand = new DelegateCommand(ExecuteSearch);
            CanSearchMovie = RegistryHelper.CanSearchMovie;
            CanSearchDirectors = RegistryHelper.CanSearchDirectors;
            CanSearchWriters = RegistryHelper.CanSearchWriters;
            CanSearchActors = RegistryHelper.CanSearchActors;
            CanSearchGenres = RegistryHelper.CanSearchGenres;
        }

        [Import]
        private LibraryDataSource DataSource { get; set; }

        public DelegateCommand SearchCommand { get; set; }

        [Import]
        private BackgroundScannerManager BackgroundScannerManager { get; set; } 

        private List<Movie> _searchResult;
        public List<Movie> SearchResult
        {
            get { return _searchResult; }
            set
            {
                _searchResult = value;
                OnPropertyChanged("SearchResult");
            }
        }

        private void ExecuteSearch(object obj)
        {
            var searchText = (string)obj;
            if(string.IsNullOrWhiteSpace(searchText))
                return;
            WaitScreen.Show();
            BackgroundScannerManager.Pause();
            new Job(j=>DoSearch(searchText)).StartBlocked();
            DataSource.SetMovieResults(SearchResult);
            BackgroundScannerManager.Resume();
            WaitScreen.Hide();
        }

        [Import]
        private WaitScreenService WaitScreen { get; set; }

        private void DoSearch(string searchText)
        {
            Debug.WriteLine("Waiting for lock at movie DoSearch");
            lock (DatabaseManager.LockObject)
            {
                Debug.WriteLine("lock at movie DoSearch");
                SearchResult = new List<Movie>();
                var writers = DatabaseManager.Instance.GetFixedLibraryItem(LibraryItemType.WriterLibrary);
                var directors = DatabaseManager.Instance.GetFixedLibraryItem(LibraryItemType.DirectorLibrary);
                var actors = DatabaseManager.Instance.GetFixedLibraryItem(LibraryItemType.ActorLibrary);
                var movieGenres = DatabaseManager.Instance.GetFixedLibraryItem(LibraryItemType.MovieGenreLibrary);

                _totalItems = GetTotalSteps(writers,directors,actors,movieGenres);
                _current = 0;
                WaitScreen.Show(_totalItems, _current);
                if (CanSearchMovie)
                    SearchMovies(searchText);
                if (CanSearchDirectors)
                {
                    SerarchLibraryItem(searchText, directors);
                }
                if (CanSearchActors)
                {
                    SerarchLibraryItem(searchText, actors);
                }
                if (CanSearchGenres)
                {
                    SerarchLibraryItem(searchText, movieGenres);
                }
                
                if (CanSearchWriters)
                {
                    SerarchLibraryItem(searchText, writers);
                }
                Debug.WriteLine("unlock at Movie DoSearch");
            }
        }

        public int GetTotalSteps(LibraryItem writers, LibraryItem directors, LibraryItem actors, LibraryItem movieGenres)
        {
            int totalSteps = 0;
            if (CanSearchMovie)
                totalSteps+=DatabaseManager.Instance.GetMovieCount();
            if (CanSearchDirectors)
            {
                totalSteps += directors.Children.Count;
            }
            if (CanSearchActors)
            {
                totalSteps += actors.Children.Count;
            }
            if (CanSearchGenres)
            {
                totalSteps += movieGenres.Children.Count;
            }
            if (CanSearchWriters)
            {
                totalSteps += writers.Children.Count;
            }
            return totalSteps;
        }

        private void SerarchLibraryItem(string searchText, LibraryItem libraryItem)
        {
            foreach (var c in libraryItem.Children)
            {
                IncreaseSteps();
                if (IsMatch(c.Title, searchText))
                {
                    foreach (var movie in c.Movies.Where(movie => SearchResult.Contains(movie) == false))
                    {
                        SearchResult.Add(movie);
                    }
                }
            }
        }

        private void SearchMovies(string searchText)
        {
            foreach (var movie in DatabaseManager.Instance.GetAllMovies())
            {
                IncreaseSteps();
                if (IsMatch(movie, searchText))
                {
                    SearchResult.Add(movie);
                }
            }
        }

        private void IncreaseSteps()
        {
            if(++_current%10==0)
                WaitScreen.Show(_totalItems, _current);
        }

        private bool IsMatch(Movie movie, string searchText)
        {
            if (CanSearchMovie)
            {
                if (IsMatch(movie.Title, searchText))
                    return true;
                if (IsMatch(movie.FullPath, searchText))
                    return true;
            }
            return false;
        }

        private static bool IsMatch(string actualData, string searchText)
        {
            return actualData!=null && Regex.IsMatch(actualData, searchText,RegexOptions.IgnoreCase);
        }


        private bool _canSearchMovie;
        public bool CanSearchMovie
        {
            get { return _canSearchMovie; }
            set
            {
                RegistryHelper.CanSearchMovie = _canSearchMovie = value;
                OnPropertyChanged("CanSearchMovie");
            }
        }

        private bool _canSearchDirectors;
        public bool CanSearchDirectors
        {
            get { return _canSearchDirectors; }
            set
            {
                RegistryHelper.CanSearchDirectors = _canSearchDirectors = value;
                OnPropertyChanged("CanSearchDirectors");
            }
        }

        private bool _canSearchWriters;
        public bool CanSearchWriters
        {
            get { return _canSearchWriters; }
            set
            {
                RegistryHelper.CanSearchWriters = _canSearchWriters = value;
                OnPropertyChanged("CanSearchWriters");
            }
        }

        private bool _canSearchActors;
        public bool CanSearchActors
        {
            get { return _canSearchActors; }
            set
            {
                RegistryHelper.CanSearchActors= _canSearchActors = value;
                OnPropertyChanged("CanSearchActors");
            }
        }

        private bool _canSearchGenres;
        private int _totalItems;
        private int _current;

        public bool CanSearchGenres
        {
            get { return _canSearchGenres; }
            set
            {
                RegistryHelper.CanSearchGenres = _canSearchGenres = value;
                OnPropertyChanged("CanSearchGenres");
            }
        }
    }
}
